package com.isyscore.os.metadata.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.isyscore.os.core.exception.DataFactoryException;
import com.isyscore.os.core.exception.ErrorCode;
import com.isyscore.os.metadata.dao.DataSourceMapper;
import com.isyscore.os.metadata.manager.DatabaseManager;
import com.isyscore.os.metadata.model.dto.DataQueryDTO;
import com.isyscore.os.metadata.model.dto.DataSourceDTO;
import com.isyscore.os.metadata.model.dto.QuerySqlResultDTO;
import com.isyscore.os.metadata.model.dto.TaskDTO;
import com.isyscore.os.metadata.model.entity.DataSource;
import com.isyscore.os.metadata.model.vo.DataQueryVO;
import com.isyscore.os.metadata.model.vo.ResultVO;
import com.isyscore.os.metadata.service.DataBuildService;
import com.isyscore.os.metadata.service.DataSourceService;
import com.isyscore.os.metadata.service.TaskService;
import com.isyscore.os.metadata.utils.UdmpBeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * @author fjZheng
 * @version 1.0
 * @date 2020/12/4 14:03
 */
@Slf4j
@Service
public class DataBuildServiceImpl implements DataBuildService {

    @Resource
    private DataSourceMapper dataSourceMapper;
    @Resource
    private DatabaseManager databaseManager;

    @Resource
    private TaskService taskService;

    @Resource
    private DataSourceService dataSourceService;


    @Override
    public DataQueryDTO executeSQL(DataQueryVO dataQueryVO, String taskId) {
        log.debug("开始异步运行SQL");
        DataSourceDTO dataSourceDTO = dataSourceService.get(dataQueryVO.getDataSourceId(), true);
        //数据源ID不存在
        if (Objects.isNull(dataSourceDTO)) {
            taskService.setTaskProgress(taskId, 100d);
        }
        dataSourceDTO.setSelectDatabaseName(dataQueryVO.getDatabaseName());

        StringBuilder stringBuilder = new StringBuilder();
        ResultVO resultVO = new ResultVO();
        taskService.setTaskProgress(taskId, 20.00);
        int isSuccess = 1;
        for (String sql : dataQueryVO.getSqlText().split(";")) {
            try {
                long startTime = System.currentTimeMillis();
                dataQueryVO.setSqlText(sql);
                resultVO = databaseManager.getTableData(dataSourceDTO, dataQueryVO);
                long endTime = System.currentTimeMillis();
                stringBuilder.append("SQL: ").append(sql).append("\n")
                        .append("运行成功\n")
                        .append("运行时间：").append(endTime - startTime).append("ms\n");
            } catch (Exception e) {
                isSuccess = 0;
                String message = DataFactoryException.getMessage(e);
                log.error("SQL 运行失败：{}\n{}", sql, message);
                stringBuilder.append("SQL：").append(sql).append("\n").append("运行失败:\n").append(message);
            }
        }
        log.debug("更新任务数据");
//        taskService.setTaskProgress(taskId, 100.00);
        TaskDTO taskDTO = taskService.get(taskId);
        taskDTO.setTaskId(taskId);
        taskDTO.setData(JSONObject.toJSONString(DataQueryDTO.builder().sqlLog(stringBuilder.toString()).data(resultVO).isSuccess(isSuccess).build()));
        taskService.update(taskDTO);
        taskService.setTaskProgress(taskId, 100.00);
        log.debug("SQL运行结束");
        return null;
//        BaseSource source = SourceFactory.getSource(DataSourceTypeEnum.getType(dataSourceDTO.getType()).getName());
//        return source.executeSQL(dataSourceDTO, dataQueryVO, taskId, taskService);
    }

    @Override
    public ResultVO getStructureBySql(DataQueryVO dataQueryVO) {
        DataSourceDTO dataSourceDTO = dataSourceService.get(dataQueryVO.getDataSourceId(), true);
        if(ObjectUtil.isNotNull(dataSourceDTO)){
            dataSourceDTO.setSelectDatabaseName(dataQueryVO.getDatabaseName());
            return databaseManager.getTableData(dataSourceDTO, dataQueryVO);
        }else {
            throw new DataFactoryException(ErrorCode.DATA_SOURCE_CONNECTION_ERROR);
        }
    }

    @Override
    public QuerySqlResultDTO executeQuerySqlSync(DataQueryVO dataQueryVO) {
        DataSourceDTO dataSourceDTO = dataSourceService.get(dataQueryVO.getDataSourceId(), true);
        //数据源ID不存在
        if (Objects.isNull(dataSourceDTO)) {
            throw new DataFactoryException(ErrorCode.DATA_SOURCE_CONNECTION_ERROR);
        }
        dataSourceDTO.setSelectDatabaseName(dataQueryVO.getDatabaseName());
        QuerySqlResultDTO resultDto = new QuerySqlResultDTO();
        try {
            ResultVO resultVO = databaseManager.page(dataSourceDTO, dataQueryVO);
            resultDto.setTotal(resultVO.getCount());
            resultDto.setResults(resultVO.getContent());
        } catch (Exception e) {
            log.error("SQL执行失败", e);
            throw new DataFactoryException(ErrorCode.SQL_EXEC_FAILED, DataFactoryException.getMessage(e));
        }
        return resultDto;
    }


    public DataSourceDTO get(Long dataSourceId) {
        DataSource dataSource = dataSourceMapper.selectById(dataSourceId);
        return toDataSourceDTO(dataSource);
    }

    private DataSourceDTO toDataSourceDTO(DataSource dataSource) {
        if (dataSource == null) {
            return null;
        }
        DataSourceDTO dataSourceDTO = UdmpBeanUtils.copy(dataSource, DataSourceDTO.class);
        dataSourceDTO.setDataSourceId(dataSource.getId());
        List<String> list = JSONObject.parseArray(dataSource.getDatabaseName(), String.class);
        dataSourceDTO.setDatabaseNameList(list);
        return dataSourceDTO;
    }
}
